Brian Durán

Proyecto II


I Parte

Se le pidió a un grupo de 100 clientes que compraron el mismo producto o productos similares en la tienda de Amazon, que evaluaran el servicio recibido desde diferentes aspectos. El archivo EjemploAlgoritmosRecomendacion.csv muestra los promedios de la evaluación dada por los clientes en relación a las variables que se pueden apreciar en el encabezado de la tabla. Para este dataset, realice lo siguiente:

  1. Cargue el dataset EjemploAlgoritmosRecomendacion.csv, verifique que la lectura de los datos es correcta.
algoritmos_recomendacion <- read.csv("ejemplo_algoritmos_recomendacion.csv", sep = ";", dec = ",", header = T,row.names = 1)
algoritmos_recomendacion
NA
  1. A manera de diagnóstico, haga una inspección de los datos presentes en el dataset y describa las variables presentes, tipos de variables, si hay datos nulos.
vis_dat(algoritmos_recomendacion)

Como se aprecia en el gráfico anterior, en el dataset, todos los datos son de tipo númerico y no hay valores nulos dentro de la información. Además las variables presentes en el dataset son las siguientes: Velocidad de entrega, precio, durabilidad, imagen producto, valor educativo, servicio retorno, tamaño paquete, calidad producto y número de estrellas.


  1. Determine si existen correlaciones importantes entre las variables del dataset, utilizando alguno de los gráficos o la matriz de correlaciones vistos en clases. Recordemos que para aplicar un ACP, es importante que existan correlaciones entre las variables.
c <- round(cor(algoritmos_recomendacion), 2)
corrplot(c)

Se puede apreciar que existe una correlación positiva fuerte entre las siguientes variables:

  1. Velocidad de entrega - Valor Educativo
  2. Velocidad de entrega - Calidad Producto
  3. Velocidad de entrega - Número Estrellas
  4. Imagen producto - valor educativo
  5. Valor Educativo - Número de estrellas
  6. Servicio Retorno - Imagen producto
  7. Calidad de Producto - Valor Educativo
  8. Calidad de producto - Numero de estrellas

También se puede ver que existe una correlación negativa fuerte entre:

  1. Velocidad Entrega - Tamaño Paquete
  2. Precio - Durabilidad


  1. Realice un ACP usando el paquete FactoMiner, creando el plano principal y el círculo de correlaciones. Superponga ambos gráficos e identifique la cantidad de clústeres que considere apropiado. Haga un análisis descriptivo de cada clúster, indique si hay variables correlacionadas y el tipo de correlación entre estas.
pca_amazon <- PCA(algoritmos_recomendacion, scale.unit=TRUE, ncp=5, graph = FALSE)
plot(pca_amazon, axes=c(1, 2), choix="ind", col.ind="red",new.plot=TRUE) 

plot(pca_amazon, axes=c(1, 2), choix="var", col.var="blue",new.plot=TRUE)

fviz_pca_biplot(pca_amazon, repel = FALSE,
                col.var = "#2E9FDF", # Variables color
                col.ind = "#696969"  # Individuals color
                )

Al realizar el círculo de correlaciones se aprecian los mismo resultados que se obtuvieron en la sección C.

pca_amazon.hcpc <- HCPC(pca_amazon, nb.clust=-1, min=2, max=3)

Se puede ver que a grades rasgos existen 2 clústeres (Es lo que la función anterior sugiere). El clúster 1 parece tender a la variable “Tamaño Paquete” mientras que el clúster 2 a “Durabilidad”. Nótese que se pueden especificar más clústeres si se deseara. E.g. 3 clústeres.

pca_amazon.hcpc <- HCPC(pca_amazon, nb.clust=3, min=2, max=3)


  1. Repita el ejercicio anterior usando el paquete FactoMineR, elimine de los gráficos los individuos con \(cos^{2}(\theta) \le 0.2\) y las variables \(cos^{2}(\theta) \le 0.55\). y vuelva a crear el plano principal y el círculo de correlaciones. ¿Cuáles individuos quedaron mal representados?, ¿cuáles variables quedaron mal representadas?

cos2_ind <- (pca_amazon$ind$cos2[,1] + pca_amazon$ind$cos2[,2])
cos2_ind
       Adam        Anna     Bernard      Edward      Emilia      Fabian      Philip       Frank      Xavier 
 0.55146960  0.74416168  0.66040342  0.63180497  0.71816555  0.45408677  0.58722302  0.58010199  0.69566981 
    Gabriel     Marisol       Henry       Irene    Isabelle     Isidore      Joseph      Eugene     Eugenia 
 0.82560843  0.54819961  0.11569585  0.91278931  0.01262467  0.65679771  0.67832572  0.36678098  0.35198240 
     Eunice         Eva     Evdokia       Fedir       Felix      Fialka      Flavia       Flora     Florent 
 0.74322200  0.67167923  0.96010202  0.95451021  0.73471903  0.88471297  0.74031145  0.64285172  0.88046658 
   Florence      Hannah       Helen      Herman      Hilary     Lourdes     Isadore        Ivan       Jacob 
 0.70968393  0.47084804  0.61788267  0.65860749  0.66203175  0.91529171  0.69287286  0.94695684  0.82260793 
   Jeremiah      Jervis     Joachim        John    Santiago   Josephine      Judith      Justin      Kalyna 
 0.64508404  0.38536779  0.79572503  0.91543082  0.77879172  0.71106364  0.56816646  0.73249315  0.84870929 
    Larissa    Lawrence        Leon     Leonard      Leonid       Lesia         Leo      Louise     Lubomyr 
 0.57507766  0.43650815  0.58953331  0.68423683  0.36960213  0.32667100  0.36794715  0.77857765  0.82560730 
      Lydia   Magdalyna      Maksym      Marcel    Margaret       Maria      Marian    Marianna     Markian 
 0.91194804  0.47874818  0.93172414  0.84840458  0.43494804  0.24534428  0.44278161  0.89383453  0.36835389 
      Marko      Martha      Martin      Maryna     Matthew       Maura        Maya Maximillian     Melania 
 0.36169774  0.69424135  0.81330948  0.80603214  0.57488340  0.59312759  0.30161325  0.72408013  0.34676297 
  Methodius     Michael  Michaelina        Mina      Monica      Mykyta       Myron    Myroslav   Myroslava 
 0.65616510  0.65367205  0.52709522  0.24566179  0.28583026  0.53832858  0.72972284  0.69287260  0.63195389 
     Salome      Samuel      Sandra       Sarah      Savina   Sebastian      Sophia     Stephan   Stephania 
 0.78699090  0.73885253  0.60739183  0.31844744  0.66295845  0.16038875  0.69378643  0.53241763  0.82140355 
    Susanna      Sylvan   Sylvester      Tamara    Theodore      Teofan      Teofil     Teofila        Teon 
 0.59612138  0.37431726  0.64600722  0.91479710  0.63831774  0.88227742  0.69857490  0.91327675  0.54270039 
     Teresa 
 0.38328345 
malrep <- NULL
# Seguidamente se seleccionan las entradas que cumplen la restricción, es decir, lo mal representados
for (i in 1 : nrow(algoritmos_recomendacion)) {
 header <- names(cos2_ind)[i]
 ifelse(cos2_ind[i] <= 0.2, malrep <- cbind(matrix(c(header, cos2_ind[i]), 2, 1, TRUE), malrep), NA)
}
malrep
     [,1]                [,2]                 [,3]               
[1,] "Sebastian"         "Isabelle"           "Henry"            
[2,] "0.160388753998423" "0.0126246707441691" "0.115695849549973"

Se puede ver que Sebastian, Isabelle y Henry están mal representados en este set de datos.


cos2_var <- (pca_amazon$var$cos2[,1] + pca_amazon$var$cos2[,2])
cos2_var
Velocidad.Entrega            Precio       Durabilidad   Imagen.Producto   Valor.Educativo  Servicio.Retorno 
        0.7977364         0.6356452         0.6812899         0.6366073         0.6900909         0.5265128 
   Tamano.Paquete  Calidad.Producto  Numero.Estrellas 
        0.5719167         0.8209417         0.7744783 
var_malrep <- NULL #crea un vector
# Seguidamente se seleccionan las entradas que cumplen la restricción, es decir, lo mal representados
for (i in 1 : nrow(algoritmos_recomendacion)) {
 header <- names(cos2_var)[i]
 ifelse(cos2_var [i] <= 0.55, var_malrep <- cbind(matrix(c(header, cos2_var[i]), 2, 1, TRUE), var_malrep), NA)
}
var_malrep
     [,1]               
[1,] "Servicio.Retorno" 
[2,] "0.526512849488411"

Según el resultado, solo la variable “Servicio Retorno” no cumple con los requisitos mínimos.


  1. Realice un gráfico radar (araña) usando 3 clústeres e interprete cada uno de los clústeres.
modelo <- hclust(dist(algoritmos_recomendacion),method= "ward.D")
#modelo

centros<-centers.hclust(algoritmos_recomendacion,modelo,nclust=3,use.median=FALSE)
#centros

rownames(centros)<-c("Cluster 1","Cluster 2","Cluster 3")
centros<-as.data.frame(centros)
centros2<-as.data.frame(centros)

maximos<-apply(centros,2,max)
minimos<-apply(centros,2,min)
centros<-rbind(minimos,centros)
centros<-rbind(maximos,centros)
centros
radarchart(centros,maxmin=TRUE,axistype=4,axislabcol="slategray4",
           centerzero=FALSE,seg=8,cglcol="gray67",
           pcol=c("blue","red","green"),
           plty=1,
           plwd=5,
           title="Comparación de clústeres")

legenda <-legend(1.5,1, legend=c("Cluster 1","Cluster 2","Cluster 3"),
                 seg.len=-1.4,
                 title="Clústeres",
                 pch=21, 
                 bty="n" ,lwd=3, y.intersp=1, horiz=FALSE,
                 col=c("blue","red","green"))

Se puede que los individuos del clúster 1 calificaron más alto el Precio y Tamaño de Paquete, los miembros del clúster 2 concordaron que el servicio fue mejor con respecto al precio, número de estrellas, calidad del producto, tamaño del paquete, servicio de retorno, valor educativo e imagen del producto. Por último lo miembros del clúster 3 percibieron el servicio recibido como positivo en los aspectos de durabilidad, Velocidad de entrega, número de estrellas, calidad del producto y valor educativo.

  1. Suponga que se trabajaron los datos con 3 clústeres, como se muestra en el plano principal siguiente:

Partiendo del hecho de que todos los individuos compraron, ya sea el mismo producto o similares, pero, cada uno tuvo una experiencia de compra diferente que pudo ser mejor o peor en los diferentes rubros de la evaluación.

  • ¿Qué productos recomendaría a Salome
  • ¿Qué productos recomendaría a Stephania?
  • ¿Qué productos recomendaría a Lydia?
Es decir, los mismos productos que compró cuál otro cliente.
fviz_pca_biplot(pca_amazon, repel = FALSE,
                col.var = "#2E9FDF", # Variables color
                col.ind = "#696969"  # Individuals color
                )

Tomando en cuenta el gráfico anterior, en el cual se superpusieron el plano principal y el círculo de correlaciones, a Salome se le pueden recomendar productos con una puntuación alta en Imagen Producto y Precio, a Stephania productos con un alto Valor Educativo y a Lydia no podríamos saber que recomendarle puesto que esta muy alejada de cualquier variable.


II Parte

Considérese tabla datos ConsumoEuropa.csv que contiene una estimación del consumo promedio de proteínas, en gramos, por persona y por día, en Europa, datos del año 1981 (Está en el aula virtual con el nombre).

  1. Usando FactoMineR efectúe un ACP para esta tabla de datos
consumo_europa <- read.csv("consumo_europa.csv", sep = ";", dec = ",", header = T,row.names = 1)
pca_europa<- PCA(consumo_europa, scale.unit=TRUE, ncp=5, graph = FALSE)
pca_europa$var
$coord
                  Dim.1       Dim.2        Dim.3      Dim.4       Dim.5
CarneAnimal   0.6103512 -0.07959861  0.604598358  0.3252356  0.02547500
CarneCerdo    0.6561937 -0.30272199 -0.587241060  0.2325802 -0.19878516
Huevos        0.8683846 -0.04608760 -0.005096851  0.3099642  0.03816592
Leche         0.6919076 -0.33712557  0.302820404  0.0222087  0.20878439
CarnePescado  0.2303011  0.85589466  0.202885747 -0.2979579 -0.18578716
Cereales     -0.8607292 -0.32678534 -0.110929934  0.0759775  0.21287360
Almidon       0.5974899  0.46549920 -0.339904098 -0.1699131  0.50869008
Semillas     -0.8297185  0.13586043  0.193878778  0.3193514  0.17632219
Frutas       -0.1960221  0.62892592 -0.168233601  0.6894679 -0.02889873

$cor
                  Dim.1       Dim.2        Dim.3      Dim.4       Dim.5
CarneAnimal   0.6103512 -0.07959861  0.604598358  0.3252356  0.02547500
CarneCerdo    0.6561937 -0.30272199 -0.587241060  0.2325802 -0.19878516
Huevos        0.8683846 -0.04608760 -0.005096851  0.3099642  0.03816592
Leche         0.6919076 -0.33712557  0.302820404  0.0222087  0.20878439
CarnePescado  0.2303011  0.85589466  0.202885747 -0.2979579 -0.18578716
Cereales     -0.8607292 -0.32678534 -0.110929934  0.0759775  0.21287360
Almidon       0.5974899  0.46549920 -0.339904098 -0.1699131  0.50869008
Semillas     -0.8297185  0.13586043  0.193878778  0.3193514  0.17632219
Frutas       -0.1960221  0.62892592 -0.168233601  0.6894679 -0.02889873

$cos2
                  Dim.1       Dim.2        Dim.3        Dim.4        Dim.5
CarneAnimal  0.37252854 0.006335939 3.655392e-01 0.1057781815 0.0006489754
CarneCerdo   0.43059019 0.091640606 3.448521e-01 0.0540935716 0.0395155400
Huevos       0.75409185 0.002124067 2.597789e-05 0.0960778220 0.0014566371
Leche        0.47873607 0.113653648 9.170020e-02 0.0004932262 0.0435909200
CarnePescado 0.05303858 0.732555674 4.116263e-02 0.0887789165 0.0345168681
Cereales     0.74085471 0.106788657 1.230545e-02 0.0057725806 0.0453151701
Almidon      0.35699416 0.216689501 1.155348e-01 0.0288704695 0.2587655951
Semillas     0.68843272 0.018458057 3.758898e-02 0.1019853039 0.0310895146
Frutas       0.03842468 0.395547814 2.830254e-02 0.4753659282 0.0008351364

$contrib
                  Dim.1      Dim.2        Dim.3       Dim.4      Dim.5
CarneAnimal   9.5185975  0.3762894 35.249277907 11.05060734  0.1424021
CarneCerdo   11.0021495  5.4425071 33.254400739  5.65113534  8.6707397
Huevos       19.2680453  0.1261477  0.002505071 10.03721438  0.3196242
Leche        12.2323404  6.7498548  8.842734093  0.05152716  9.5649844
CarnePescado  1.3552059 43.5062538  3.969349808  9.27470043  7.5739008
Cereales     18.9298189  6.3421451  1.186625849  0.60305935  9.9433298
Almidon       9.1216734 12.8691221 11.141126308  3.01608723 56.7799182
Semillas     17.5903676  1.0962183  3.624739889 10.65436682  6.8218501
Frutas        0.9818014 23.4914617  2.729240336 49.66130196  0.1832507
  1. Grafique el plano principal y el círculo de correlaciones, luego compare este Plano Principal con el mapa de Europa ¿Qué conclusiones puede sacar?
plot(pca_europa, axes=c(1, 2), choix="ind", col.ind="red",new.plot=TRUE)

plot(pca_europa, axes=c(1, 2), choix="var", col.var="blue",new.plot=TRUE) 

Considere que podría recortar alguno de estos gráficos, hacer rotaciones y si es necesario buscar un mapa de Europa, de preferencia un mapa político.


Según el plano principal, el círculo de correlaciones y el mapa de europa, se puede apreciar que la mayoría de europa obtiene su fuente de proteínas de carne animal, huevos, carne de cerdo, leche y cereales. Pero España y Portugal tienen al pescado y las frutas como fuente principal.

 


Autor Brian Duran

 

LS0tDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgY3NzOiAuLi9zdHlsZXMvc3RhbmRhcmRfc3R5bGVzLmNzcw0KLS0tDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeShjb3JycikNCmxpYnJhcnkoZ2djb3JycGxvdCkNCmxpYnJhcnkoR0dhbGx5KQ0KbGlicmFyeSh2aXNkYXQpDQpsaWJyYXJ5KHJhdHRsZSkNCmxpYnJhcnkoZm1zYikNCmxpYnJhcnkoRmFjdG9NaW5lUikNCmxpYnJhcnkoZmFjdG9leHRyYSkNCmBgYA0KDQoNCiMjIyBCcmlhbiBEdXLDoW4NCg0KIVtdKC4uL2xvZ29fY2llbmNpYV9kZV9kYXRvcy5wbmcpDQoNCjxoMT48Y2VudGVyPiBQcm95ZWN0byBJSSA8L2NlbnRlcj48L2gxPg0KDQo8L2JyPg0KDQojIyMjIEkgUGFydGUNCg0KU2UgbGUgcGlkacOzIGEgdW4gZ3J1cG8gZGUgMTAwIGNsaWVudGVzIHF1ZSBjb21wcmFyb24gZWwgbWlzbW8gcHJvZHVjdG8gbyBwcm9kdWN0b3Mgc2ltaWxhcmVzIGVuIGxhIHRpZW5kYSBkZSBBbWF6b24sIHF1ZSBldmFsdWFyYW4gZWwgc2VydmljaW8gcmVjaWJpZG8gZGVzZGUgZGlmZXJlbnRlcyBhc3BlY3Rvcy4gRWwgYXJjaGl2byBFamVtcGxvQWxnb3JpdG1vc1JlY29tZW5kYWNpb24uY3N2IG11ZXN0cmEgbG9zIHByb21lZGlvcyBkZSBsYSBldmFsdWFjacOzbiBkYWRhIHBvciBsb3MgY2xpZW50ZXMgZW4gcmVsYWNpw7NuIGEgbGFzIHZhcmlhYmxlcyBxdWUgc2UgcHVlZGVuIGFwcmVjaWFyIGVuIGVsIGVuY2FiZXphZG8gZGUgbGEgdGFibGEuIFBhcmEgZXN0ZSBkYXRhc2V0LCByZWFsaWNlIGxvIHNpZ3VpZW50ZToNCg0KICBhKSBDYXJndWUgZWwgZGF0YXNldCBFamVtcGxvQWxnb3JpdG1vc1JlY29tZW5kYWNpb24uY3N2LCB2ZXJpZmlxdWUgcXVlIGxhIGxlY3R1cmEgZGUgbG9zIGRhdG9zDQogIGVzIGNvcnJlY3RhLg0KICANCmBgYHtyLCBjbGFzcy5zb3VyY2U9ImluZGVudCIsIGNsYXNzLm91dHB1dD0iaW5kZW50In0NCmFsZ29yaXRtb3NfcmVjb21lbmRhY2lvbiA8LSByZWFkLmNzdigiZWplbXBsb19hbGdvcml0bW9zX3JlY29tZW5kYWNpb24uY3N2Iiwgc2VwID0gIjsiLCBkZWMgPSAiLCIsIGhlYWRlciA9IFQscm93Lm5hbWVzID0gMSkNCmFsZ29yaXRtb3NfcmVjb21lbmRhY2lvbg0KDQpgYGANCiAgDQogIGIpIEEgbWFuZXJhIGRlIGRpYWduw7NzdGljbywgaGFnYSB1bmEgaW5zcGVjY2nDs24gZGUgbG9zIGRhdG9zIHByZXNlbnRlcyBlbiBlbCBkYXRhc2V0IHkNCiAgZGVzY3JpYmEgbGFzIHZhcmlhYmxlcyBwcmVzZW50ZXMsIHRpcG9zIGRlIHZhcmlhYmxlcywgc2kgaGF5IGRhdG9zIG51bG9zLg0KICANCmBgYHtyfQ0KdmlzX2RhdChhbGdvcml0bW9zX3JlY29tZW5kYWNpb24pDQoNCmBgYA0KICANCkNvbW8gc2UgYXByZWNpYSBlbiBlbCBncsOhZmljbyBhbnRlcmlvciwgZW4gZWwgZGF0YXNldCwgdG9kb3MgbG9zIGRhdG9zIHNvbiBkZSB0aXBvIG7Dum1lcmljbyB5IG5vIGhheSB2YWxvcmVzIG51bG9zIGRlbnRybyBkZSBsYSBpbmZvcm1hY2nDs24uIEFkZW3DoXMgbGFzIHZhcmlhYmxlcyBwcmVzZW50ZXMgZW4gZWwgZGF0YXNldCBzb24gbGFzIHNpZ3VpZW50ZXM6IFZlbG9jaWRhZCBkZSBlbnRyZWdhLCBwcmVjaW8sIGR1cmFiaWxpZGFkLCBpbWFnZW4gcHJvZHVjdG8sIHZhbG9yIGVkdWNhdGl2bywgc2VydmljaW8gcmV0b3JubywgdGFtYcOxbyBwYXF1ZXRlLCBjYWxpZGFkIHByb2R1Y3RvIHkgbsO6bWVybyBkZSBlc3RyZWxsYXMuDQoNCjwvYnI+DQoNCiAgYykgRGV0ZXJtaW5lIHNpIGV4aXN0ZW4gY29ycmVsYWNpb25lcyBpbXBvcnRhbnRlcyBlbnRyZSBsYXMgdmFyaWFibGVzIGRlbCBkYXRhc2V0LCB1dGlsaXphbmRvDQogIGFsZ3VubyBkZSBsb3MgZ3LDoWZpY29zIG8gbGEgbWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgdmlzdG9zIGVuIGNsYXNlcy4gUmVjb3JkZW1vcyBxdWUgcGFyYQ0KICBhcGxpY2FyIHVuIEFDUCwgZXMgaW1wb3J0YW50ZSBxdWUgZXhpc3RhbiBjb3JyZWxhY2lvbmVzIGVudHJlIGxhcyB2YXJpYWJsZXMuDQogIA0KYGBge3J9DQpjIDwtIHJvdW5kKGNvcihhbGdvcml0bW9zX3JlY29tZW5kYWNpb24pLCAyKQ0KY29ycnBsb3QoYykNCmBgYA0KICANClNlIHB1ZWRlIGFwcmVjaWFyIHF1ZSBleGlzdGUgdW5hIGNvcnJlbGFjacOzbiBwb3NpdGl2YSBmdWVydGUgZW50cmUgbGFzIHNpZ3VpZW50ZXMgdmFyaWFibGVzOg0KICANCiAgMS4gVmVsb2NpZGFkIGRlIGVudHJlZ2EgLSBWYWxvciBFZHVjYXRpdm8NCiAgMi4gVmVsb2NpZGFkIGRlIGVudHJlZ2EgLSBDYWxpZGFkIFByb2R1Y3RvDQogIDMuIFZlbG9jaWRhZCBkZSBlbnRyZWdhIC0gTsO6bWVybyBFc3RyZWxsYXMNCiAgNC4gSW1hZ2VuIHByb2R1Y3RvIC0gdmFsb3IgZWR1Y2F0aXZvDQogIDUuIFZhbG9yIEVkdWNhdGl2byAtIE7Dum1lcm8gZGUgZXN0cmVsbGFzDQogIDYuIFNlcnZpY2lvIFJldG9ybm8gLSBJbWFnZW4gcHJvZHVjdG8NCiAgNy4gQ2FsaWRhZCBkZSBQcm9kdWN0byAtIFZhbG9yIEVkdWNhdGl2bw0KICA4LiBDYWxpZGFkIGRlIHByb2R1Y3RvIC0gTnVtZXJvIGRlIGVzdHJlbGxhcw0KICANClRhbWJpw6luIHNlIHB1ZWRlIHZlciBxdWUgZXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gbmVnYXRpdmEgZnVlcnRlIGVudHJlOg0KICANCiAgMS4gVmVsb2NpZGFkIEVudHJlZ2EgLSBUYW1hw7FvIFBhcXVldGUNCiAgMi4gUHJlY2lvIC0gRHVyYWJpbGlkYWQNCiAgDQogIDwvYnI+DQogIA0KICANCiAgZCkgUmVhbGljZSB1biBBQ1AgdXNhbmRvIGVsIHBhcXVldGUgRmFjdG9NaW5lciwgY3JlYW5kbyBlbCBwbGFubyBwcmluY2lwYWwgeSBlbCBjw61yY3VsbyBkZQ0KICBjb3JyZWxhY2lvbmVzLiBTdXBlcnBvbmdhIGFtYm9zIGdyw6FmaWNvcyBlIGlkZW50aWZpcXVlIGxhIGNhbnRpZGFkIGRlIGNsw7pzdGVyZXMgcXVlIGNvbnNpZGVyZQ0KICBhcHJvcGlhZG8uIEhhZ2EgdW4gYW7DoWxpc2lzIGRlc2NyaXB0aXZvIGRlIGNhZGEgY2zDunN0ZXIsIGluZGlxdWUgc2kgaGF5IHZhcmlhYmxlcw0KICBjb3JyZWxhY2lvbmFkYXMgeSBlbCB0aXBvIGRlIGNvcnJlbGFjacOzbiBlbnRyZSBlc3Rhcy4NCg0KYGBge3J9DQpwY2FfYW1hem9uIDwtIFBDQShhbGdvcml0bW9zX3JlY29tZW5kYWNpb24sIHNjYWxlLnVuaXQ9VFJVRSwgbmNwPTUsIGdyYXBoID0gRkFMU0UpDQpwbG90KHBjYV9hbWF6b24sIGF4ZXM9YygxLCAyKSwgY2hvaXg9ImluZCIsIGNvbC5pbmQ9InJlZCIsbmV3LnBsb3Q9VFJVRSkgDQpgYGANCg0KYGBge3J9DQpwbG90KHBjYV9hbWF6b24sIGF4ZXM9YygxLCAyKSwgY2hvaXg9InZhciIsIGNvbC52YXI9ImJsdWUiLG5ldy5wbG90PVRSVUUpDQpgYGANCg0KDQpgYGB7cn0NCmZ2aXpfcGNhX2JpcGxvdChwY2FfYW1hem9uLCByZXBlbCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIGNvbC52YXIgPSAiIzJFOUZERiIsICMgVmFyaWFibGVzIGNvbG9yDQogICAgICAgICAgICAgICAgY29sLmluZCA9ICIjNjk2OTY5IiAgIyBJbmRpdmlkdWFscyBjb2xvcg0KICAgICAgICAgICAgICAgICkNCmBgYA0KDQpBbCByZWFsaXphciBlbCBjw61yY3VsbyBkZSBjb3JyZWxhY2lvbmVzIHNlIGFwcmVjaWFuIGxvcyBtaXNtbyByZXN1bHRhZG9zIHF1ZSBzZSBvYnR1dmllcm9uIGVuIGxhIHNlY2Npw7NuICoqQyoqLg0KDQoNCmBgYHtyfQ0KcGNhX2FtYXpvbi5oY3BjIDwtIEhDUEMocGNhX2FtYXpvbiwgbmIuY2x1c3Q9LTEsIG1pbj0yLCBtYXg9MykNCmBgYA0KDQpTZSBwdWVkZSB2ZXIgcXVlIGEgZ3JhZGVzIHJhc2dvcyBleGlzdGVuIDIgY2zDunN0ZXJlcyAoRXMgbG8gcXVlIGxhIGZ1bmNpw7NuIGFudGVyaW9yIHN1Z2llcmUpLiBFbCBjbMO6c3RlciAxIHBhcmVjZSB0ZW5kZXIgYSBsYSB2YXJpYWJsZSAiVGFtYcOxbyBQYXF1ZXRlIiBtaWVudHJhcyBxdWUgZWwgY2zDunN0ZXIgMiBhICJEdXJhYmlsaWRhZCIuIE7Ds3Rlc2UgcXVlIHNlIHB1ZWRlbiBlc3BlY2lmaWNhciBtw6FzIGNsw7pzdGVyZXMgc2kgc2UgZGVzZWFyYS4gRS5nLiAzIGNsw7pzdGVyZXMuDQoNCmBgYHtyfQ0KcGNhX2FtYXpvbi5oY3BjIDwtIEhDUEMocGNhX2FtYXpvbiwgbmIuY2x1c3Q9MywgbWluPTIsIG1heD0zKQ0KYGBgDQoNCg0KPGJyPiAgDQogIA0KICBlKSBSZXBpdGEgZWwgZWplcmNpY2lvIGFudGVyaW9yIHVzYW5kbyBlbCBwYXF1ZXRlIEZhY3RvTWluZVIsIGVsaW1pbmUgZGUgbG9zIGdyw6FmaWNvcyBsb3MNCiAgaW5kaXZpZHVvcyBjb24gJGNvc157Mn0oXHRoZXRhKSBcbGUgMC4yJCB5IGxhcyB2YXJpYWJsZXMgJGNvc157Mn0oXHRoZXRhKSBcbGUgMC41NSQuIHkgdnVlbHZhDQogIGEgY3JlYXIgZWwgcGxhbm8gcHJpbmNpcGFsIHkgZWwgY8OtcmN1bG8gZGUgY29ycmVsYWNpb25lcy4gwr9DdcOhbGVzIGluZGl2aWR1b3MgcXVlZGFyb24gbWFsDQogIHJlcHJlc2VudGFkb3M/LCDCv2N1w6FsZXMgdmFyaWFibGVzIHF1ZWRhcm9uIG1hbCByZXByZXNlbnRhZGFzPw0KDQpgYGB7cn0NCg0KY29zMl9pbmQgPC0gKHBjYV9hbWF6b24kaW5kJGNvczJbLDFdICsgcGNhX2FtYXpvbiRpbmQkY29zMlssMl0pDQpjb3MyX2luZA0KDQptYWxyZXAgPC0gTlVMTA0KIyBTZWd1aWRhbWVudGUgc2Ugc2VsZWNjaW9uYW4gbGFzIGVudHJhZGFzIHF1ZSBjdW1wbGVuIGxhIHJlc3RyaWNjacOzbiwgZXMgZGVjaXIsIGxvIG1hbCByZXByZXNlbnRhZG9zDQpmb3IgKGkgaW4gMSA6IG5yb3coYWxnb3JpdG1vc19yZWNvbWVuZGFjaW9uKSkgew0KIGhlYWRlciA8LSBuYW1lcyhjb3MyX2luZClbaV0NCiBpZmVsc2UoY29zMl9pbmRbaV0gPD0gMC4yLCBtYWxyZXAgPC0gY2JpbmQobWF0cml4KGMoaGVhZGVyLCBjb3MyX2luZFtpXSksIDIsIDEsIFRSVUUpLCBtYWxyZXApLCBOQSkNCn0NCm1hbHJlcA0KDQpgYGANCg0KU2UgcHVlZGUgdmVyIHF1ZSBTZWJhc3RpYW4sIElzYWJlbGxlIHkgSGVucnkgZXN0w6FuIG1hbCByZXByZXNlbnRhZG9zIGVuIGVzdGUgc2V0IGRlIGRhdG9zLg0KDQoNCmBgYHtyfQ0KDQpjb3MyX3ZhciA8LSAocGNhX2FtYXpvbiR2YXIkY29zMlssMV0gKyBwY2FfYW1hem9uJHZhciRjb3MyWywyXSkNCmNvczJfdmFyDQoNCnZhcl9tYWxyZXAgPC0gTlVMTCAjY3JlYSB1biB2ZWN0b3INCiMgU2VndWlkYW1lbnRlIHNlIHNlbGVjY2lvbmFuIGxhcyBlbnRyYWRhcyBxdWUgY3VtcGxlbiBsYSByZXN0cmljY2nDs24sIGVzIGRlY2lyLCBsbyBtYWwgcmVwcmVzZW50YWRvcw0KZm9yIChpIGluIDEgOiBucm93KGFsZ29yaXRtb3NfcmVjb21lbmRhY2lvbikpIHsNCiBoZWFkZXIgPC0gbmFtZXMoY29zMl92YXIpW2ldDQogaWZlbHNlKGNvczJfdmFyIFtpXSA8PSAwLjU1LCB2YXJfbWFscmVwIDwtIGNiaW5kKG1hdHJpeChjKGhlYWRlciwgY29zMl92YXJbaV0pLCAyLCAxLCBUUlVFKSwgdmFyX21hbHJlcCksIE5BKQ0KfQ0KdmFyX21hbHJlcA0KDQpgYGANCg0KU2Vnw7puIGVsIHJlc3VsdGFkbywgc29sbyBsYSB2YXJpYWJsZSAiU2VydmljaW8gUmV0b3JubyIgbm8gY3VtcGxlIGNvbiBsb3MgcmVxdWlzaXRvcyBtw61uaW1vcy4NCg0KPC9icj4NCg0KICBmKSBSZWFsaWNlIHVuIGdyw6FmaWNvIHJhZGFyIChhcmHDsWEpIHVzYW5kbyAzIGNsw7pzdGVyZXMgZSBpbnRlcnByZXRlIGNhZGEgdW5vIGRlIGxvcw0KICBjbMO6c3RlcmVzLg0KDQpgYGB7cn0NCm1vZGVsbyA8LSBoY2x1c3QoZGlzdChhbGdvcml0bW9zX3JlY29tZW5kYWNpb24pLG1ldGhvZD0gIndhcmQuRCIpDQojbW9kZWxvDQoNCmNlbnRyb3M8LWNlbnRlcnMuaGNsdXN0KGFsZ29yaXRtb3NfcmVjb21lbmRhY2lvbixtb2RlbG8sbmNsdXN0PTMsdXNlLm1lZGlhbj1GQUxTRSkNCiNjZW50cm9zDQoNCnJvd25hbWVzKGNlbnRyb3MpPC1jKCJDbHVzdGVyIDEiLCJDbHVzdGVyIDIiLCJDbHVzdGVyIDMiKQ0KY2VudHJvczwtYXMuZGF0YS5mcmFtZShjZW50cm9zKQ0KY2VudHJvczI8LWFzLmRhdGEuZnJhbWUoY2VudHJvcykNCg0KbWF4aW1vczwtYXBwbHkoY2VudHJvcywyLG1heCkNCm1pbmltb3M8LWFwcGx5KGNlbnRyb3MsMixtaW4pDQpjZW50cm9zPC1yYmluZChtaW5pbW9zLGNlbnRyb3MpDQpjZW50cm9zPC1yYmluZChtYXhpbW9zLGNlbnRyb3MpDQpjZW50cm9zDQpgYGANCg0KYGBge3J9DQpyYWRhcmNoYXJ0KGNlbnRyb3MsbWF4bWluPVRSVUUsYXhpc3R5cGU9NCxheGlzbGFiY29sPSJzbGF0ZWdyYXk0IiwNCiAgICAgICAgICAgY2VudGVyemVybz1GQUxTRSxzZWc9OCxjZ2xjb2w9ImdyYXk2NyIsDQogICAgICAgICAgIHBjb2w9YygiYmx1ZSIsInJlZCIsImdyZWVuIiksDQogICAgICAgICAgIHBsdHk9MSwNCiAgICAgICAgICAgcGx3ZD01LA0KICAgICAgICAgICB0aXRsZT0iQ29tcGFyYWNpw7NuIGRlIGNsw7pzdGVyZXMiKQ0KDQpsZWdlbmRhIDwtbGVnZW5kKDEuNSwxLCBsZWdlbmQ9YygiQ2x1c3RlciAxIiwiQ2x1c3RlciAyIiwiQ2x1c3RlciAzIiksDQogICAgICAgICAgICAgICAgIHNlZy5sZW49LTEuNCwNCiAgICAgICAgICAgICAgICAgdGl0bGU9IkNsw7pzdGVyZXMiLA0KICAgICAgICAgICAgICAgICBwY2g9MjEsIA0KICAgICAgICAgICAgICAgICBidHk9Im4iICxsd2Q9MywgeS5pbnRlcnNwPTEsIGhvcml6PUZBTFNFLA0KICAgICAgICAgICAgICAgICBjb2w9YygiYmx1ZSIsInJlZCIsImdyZWVuIikpDQpgYGANCg0KU2UgcHVlZGUgcXVlIGxvcyBpbmRpdmlkdW9zIGRlbCAqKmNsw7pzdGVyIDEqKiBjYWxpZmljYXJvbiBtw6FzIGFsdG8gZWwgKipQcmVjaW8qKiB5ICoqVGFtYcOxbyBkZSBQYXF1ZXRlKiosIGxvcyBtaWVtYnJvcyBkZWwgKipjbMO6c3RlciAyKiogY29uY29yZGFyb24gcXVlIGVsIHNlcnZpY2lvIGZ1ZSBtZWpvciBjb24gcmVzcGVjdG8gYWwgKipwcmVjaW8sIG7Dum1lcm8gZGUgZXN0cmVsbGFzLCBjYWxpZGFkIGRlbCBwcm9kdWN0bywgdGFtYcOxbyBkZWwgcGFxdWV0ZSwgc2VydmljaW8gZGUgcmV0b3JubywgdmFsb3IgZWR1Y2F0aXZvIGUgaW1hZ2VuIGRlbCBwcm9kdWN0byoqLiBQb3Igw7psdGltbyBsbyBtaWVtYnJvcyBkZWwgKipjbMO6c3RlciAzKiogcGVyY2liaWVyb24gZWwgc2VydmljaW8gcmVjaWJpZG8gY29tbyBwb3NpdGl2byBlbiBsb3MgYXNwZWN0b3MgZGUgKipkdXJhYmlsaWRhZCwgVmVsb2NpZGFkIGRlIGVudHJlZ2EsIG7Dum1lcm8gZGUgZXN0cmVsbGFzLCBjYWxpZGFkIGRlbCBwcm9kdWN0byB5IHZhbG9yIGVkdWNhdGl2byoqLg0KDQoNCiAgZykgU3Vwb25nYSBxdWUgc2UgdHJhYmFqYXJvbiBsb3MgZGF0b3MgY29uIDMgY2zDunN0ZXJlcywgY29tbyBzZSBtdWVzdHJhIGVuIGVsIHBsYW5vIHByaW5jaXBhbA0KICBzaWd1aWVudGU6DQoNCiAgPGNlbnRlcj4gIVtdKGdyYWZpY29zX2cucG5nKSA8L2NlbnRlcj4NCg0KDQo8ZGl2IGNsYXNzPSJ0ZXh0LWluZGVudCI+UGFydGllbmRvIGRlbCBoZWNobyBkZSBxdWUgdG9kb3MgbG9zIGluZGl2aWR1b3MgY29tcHJhcm9uLCB5YSBzZWEgZWwgbWlzbW8gcHJvZHVjdG8gbyBzaW1pbGFyZXMsIHBlcm8sIGNhZGEgdW5vIHR1dm8gdW5hIGV4cGVyaWVuY2lhIGRlIGNvbXByYSBkaWZlcmVudGUgcXVlIHB1ZG8gc2VyIG1lam9yIG8gcGVvciBlbiBsb3MgZGlmZXJlbnRlcyBydWJyb3MgZGUgbGEgZXZhbHVhY2nDs24uDQoNCiAgPHVsPg0KICA8bGk+wr9RdcOpIHByb2R1Y3RvcyByZWNvbWVuZGFyw61hIGEgU2Fsb21lPC9saT4NCiAgPGxpPsK/UXXDqSBwcm9kdWN0b3MgcmVjb21lbmRhcsOtYSBhIFN0ZXBoYW5pYT88L2xpPg0KICA8bGk+wr9RdcOpIHByb2R1Y3RvcyByZWNvbWVuZGFyw61hIGEgTHlkaWE/PC9saT4NCiAgPC91bD4NCg0KICBFcyBkZWNpciwgbG9zIG1pc21vcyBwcm9kdWN0b3MgcXVlIGNvbXByw7MgY3XDoWwgb3RybyBjbGllbnRlLg0KPC9kaXY+DQoNCg0KYGBge3J9DQpmdml6X3BjYV9iaXBsb3QocGNhX2FtYXpvbiwgcmVwZWwgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICBjb2wudmFyID0gIiMyRTlGREYiLCAjIFZhcmlhYmxlcyBjb2xvcg0KICAgICAgICAgICAgICAgIGNvbC5pbmQgPSAiIzY5Njk2OSIgICMgSW5kaXZpZHVhbHMgY29sb3INCiAgICAgICAgICAgICAgICApDQpgYGANCg0KVG9tYW5kbyBlbiBjdWVudGEgZWwgZ3LDoWZpY28gYW50ZXJpb3IsIGVuIGVsIGN1YWwgc2Ugc3VwZXJwdXNpZXJvbiBlbCBwbGFubyBwcmluY2lwYWwgeSBlbCBjw61yY3VsbyBkZSBjb3JyZWxhY2lvbmVzLCBhICoqU2Fsb21lKiogc2UgbGUgcHVlZGVuIHJlY29tZW5kYXIgcHJvZHVjdG9zIGNvbiB1bmEgcHVudHVhY2nDs24gYWx0YSBlbiAqKkltYWdlbiBQcm9kdWN0byoqIHkgKipQcmVjaW8qKiwgYSAqKlN0ZXBoYW5pYSoqIHByb2R1Y3RvcyBjb24gdW4gYWx0byAqKlZhbG9yIEVkdWNhdGl2byoqIHkgYSAqKkx5ZGlhKiogbm8gcG9kcsOtYW1vcyBzYWJlciBxdWUgcmVjb21lbmRhcmxlIHB1ZXN0byBxdWUgZXN0YSBtdXkgYWxlamFkYSBkZSBjdWFscXVpZXIgdmFyaWFibGUuDQoNCg0KPC9icj4NCg0KDQojIyMjIElJIFBhcnRlDQoNCkNvbnNpZMOpcmVzZSB0YWJsYSBkYXRvcyBDb25zdW1vRXVyb3BhLmNzdiBxdWUgY29udGllbmUgdW5hIGVzdGltYWNpw7NuIGRlbCBjb25zdW1vIHByb21lZGlvIGRlDQpwcm90ZcOtbmFzLCBlbiBncmFtb3MsIHBvciBwZXJzb25hIHkgcG9yIGTDrWEsIGVuIEV1cm9wYSwgZGF0b3MgZGVsIGHDsW8gMTk4MSAoRXN0w6EgZW4gZWwgYXVsYQ0KdmlydHVhbCBjb24gZWwgbm9tYnJlKS4NCg0KDQogIGEpIFVzYW5kbyBGYWN0b01pbmVSIGVmZWN0w7plIHVuIEFDUCBwYXJhIGVzdGEgdGFibGEgZGUgZGF0b3MNCmBgYHtyfQ0KY29uc3Vtb19ldXJvcGEgPC0gcmVhZC5jc3YoImNvbnN1bW9fZXVyb3BhLmNzdiIsIHNlcCA9ICI7IiwgZGVjID0gIiwiLCBoZWFkZXIgPSBULHJvdy5uYW1lcyA9IDEpDQpwY2FfZXVyb3BhPC0gUENBKGNvbnN1bW9fZXVyb3BhLCBzY2FsZS51bml0PVRSVUUsIG5jcD01LCBncmFwaCA9IEZBTFNFKQ0KcGNhX2V1cm9wYSR2YXINCmBgYA0KDQoNCiAgDQogIGIpIEdyYWZpcXVlIGVsIHBsYW5vIHByaW5jaXBhbCB5IGVsIGPDrXJjdWxvIGRlIGNvcnJlbGFjaW9uZXMsIGx1ZWdvIGNvbXBhcmUgZXN0ZSBQbGFubw0KICBQcmluY2lwYWwgY29uIGVsIG1hcGEgZGUgRXVyb3BhIMK/UXXDqSBjb25jbHVzaW9uZXMgcHVlZGUgc2FjYXI/DQogIA0KYGBge3J9DQpwbG90KHBjYV9ldXJvcGEsIGF4ZXM9YygxLCAyKSwgY2hvaXg9ImluZCIsIGNvbC5pbmQ9InJlZCIsbmV3LnBsb3Q9VFJVRSkNCmBgYA0KDQpgYGB7cn0NCnBsb3QocGNhX2V1cm9wYSwgYXhlcz1jKDEsIDIpLCBjaG9peD0idmFyIiwgY29sLnZhcj0iYmx1ZSIsbmV3LnBsb3Q9VFJVRSkgDQpgYGANCiAgDQpDb25zaWRlcmUgcXVlIHBvZHLDrWEgcmVjb3J0YXIgYWxndW5vIGRlIGVzdG9zIGdyw6FmaWNvcywgaGFjZXIgcm90YWNpb25lcyB5IHNpIGVzIG5lY2VzYXJpbyBidXNjYXINCnVuIG1hcGEgZGUgRXVyb3BhLCBkZSBwcmVmZXJlbmNpYSB1biBtYXBhIHBvbMOtdGljby4NCg0KPGNlbnRlcj4gIVtdKGV1cm9wZV9tYXAuanBnKSA8L2NlbnRlcj4NCg0KPC9icj4NCg0KU2Vnw7puIGVsIHBsYW5vIHByaW5jaXBhbCwgZWwgY8OtcmN1bG8gZGUgY29ycmVsYWNpb25lcyB5IGVsIG1hcGEgZGUgZXVyb3BhLCBzZSBwdWVkZSBhcHJlY2lhciBxdWUgbGEgbWF5b3LDrWEgZGUgZXVyb3BhIG9idGllbmUgc3UgZnVlbnRlIGRlIHByb3Rlw61uYXMgZGUgY2FybmUgYW5pbWFsLCBodWV2b3MsIGNhcm5lIGRlIGNlcmRvLCBsZWNoZSB5IGNlcmVhbGVzLiBQZXJvIEVzcGHDsWEgeSBQb3J0dWdhbCB0aWVuZW4gYWwgcGVzY2FkbyB5IGxhcyBmcnV0YXMgY29tbyBmdWVudGUgcHJpbmNpcGFsLg0KDQoNCg0KDQoNCjwhLS0gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLS0+DQo8IS0tDQpFc3RhIHNlY2Npw7NuIGVzIHNvbG8gcGFyYSBhZ3JlZ2FyIGVzdGlsb3MgeSBlbGVtZW50b3MgDQpwZXJzb25hbGl6YWRvcyBhbCBodG1sIGdlbmVyYWRvIHBvciByU3R1ZGlvICANCi0tPg0KPCEtLSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAtLT4NCg0KJm5ic3A7DQoNCjxociAvPg0KPHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPkF1dG9yIDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9iZHVyYW5zIj5CcmlhbiBEdXJhbjwvYT48L3A+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PHNwYW4gc3R5bGU9ImNvbG9yOiAjODA4MDgwOyI+PGVtPmJkdXJhbjAzOTNAZ21haWwuY29tPC9lbT48L3NwYW4+PC9wPg0KDQo8IS0tIEFkZCBpY29uIGxpYnJhcnkgLS0+DQo8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL2ZvbnQtYXdlc29tZS80LjcuMC9jc3MvZm9udC1hd2Vzb21lLm1pbi5jc3MiPg0KDQo8IS0tIEFkZCBmb250IGF3ZXNvbWUgaWNvbnMgLS0+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+DQogICAgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL2JkdXJhbnMvdGVjX2RhdGFfc2NpZW5jZV9jb3Vyc2UvdHJlZS9tYXN0ZXIvbWF0aGVtYXRpY3NfZm9yX2RhdGFfc2NpZW5jZS9zZWNvbmRfcHJvamVjdCIgY2xhc3M9ImZhIGZhLWdpdGh1YiI+PC9hPg0KPC9wPg0KDQo8YSBocmVmPSJodHRwczovL2dpdGh1Yi5jb20vYmR1cmFucy90ZWNfZGF0YV9zY2llbmNlX2NvdXJzZS90cmVlL21hc3Rlci9tYXRoZW1hdGljc19mb3JfZGF0YV9zY2llbmNlL3NlY29uZF9wcm9qZWN0IiBjbGFzcz0iZ2l0aHViLWNvcm5lciIgYXJpYS1sYWJlbD0iVmlldyBzb3VyY2Ugb24gR2l0SHViIj48c3ZnIHdpZHRoPSI4MCIgaGVpZ2h0PSI4MCIgdmlld0JveD0iMCAwIDI1MCAyNTAiIHN0eWxlPSJmaWxsOiMxNTE1MTM7IGNvbG9yOiNmZmY7IHBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOiAwOyBib3JkZXI6IDA7IHJpZ2h0OiAwOyIgYXJpYS1oaWRkZW49InRydWUiPjxwYXRoIGQ9Ik0wLDAgTDExNSwxMTUgTDEzMCwxMTUgTDE0MiwxNDIgTDI1MCwyNTAgTDI1MCwwIFoiPjwvcGF0aD48cGF0aCBkPSJNMTI4LjMsMTA5LjAgQzExMy44LDk5LjcgMTE5LjAsODkuNiAxMTkuMCw4OS42IEMxMjIuMCw4Mi43IDEyMC41LDc4LjYgMTIwLjUsNzguNiBDMTE5LjIsNzIuMCAxMjMuNCw3Ni4zIDEyMy40LDc2LjMgQzEyNy4zLDgwLjkgMTI1LjUsODcuMyAxMjUuNSw4Ny4zIEMxMjIuOSw5Ny42IDEzMC42LDEwMS45IDEzNC40LDEwMy4yIiBmaWxsPSJjdXJyZW50Q29sb3IiIHN0eWxlPSJ0cmFuc2Zvcm0tb3JpZ2luOiAxMzBweCAxMDZweDsiIGNsYXNzPSJvY3RvLWFybSI+PC9wYXRoPjxwYXRoIGQ9Ik0xMTUuMCwxMTUuMCBDMTE0LjksMTE1LjEgMTE4LjcsMTE2LjUgMTE5LjgsMTE1LjQgTDEzMy43LDEwMS42IEMxMzYuOSw5OS4yIDEzOS45LDk4LjQgMTQyLjIsOTguNiBDMTMzLjgsODguMCAxMjcuNSw3NC40IDE0My44LDU4LjAgQzE0OC41LDUzLjQgMTU0LjAsNTEuMiAxNTkuNyw1MS4wIEMxNjAuMyw0OS40IDE2My4yLDQzLjYgMTcxLjQsNDAuMSBDMTcxLjQsNDAuMSAxNzYuMSw0Mi41IDE3OC44LDU2LjIgQzE4My4xLDU4LjYgMTg3LjIsNjEuOCAxOTAuOSw2NS40IEMxOTQuNSw2OS4wIDE5Ny43LDczLjIgMjAwLjEsNzcuNiBDMjEzLjgsODAuMiAyMTYuMyw4NC45IDIxNi4zLDg0LjkgQzIxMi43LDkzLjEgMjA2LjksOTYuMCAyMDUuNCw5Ni42IEMyMDUuMSwxMDIuNCAyMDMuMCwxMDcuOCAxOTguMywxMTIuNSBDMTgxLjksMTI4LjkgMTY4LjMsMTIyLjUgMTU3LjcsMTE0LjEgQzE1Ny45LDExNi45IDE1Ni43LDEyMC45IDE1Mi43LDEyNC45IEwxNDEuMCwxMzYuNSBDMTM5LjgsMTM3LjcgMTQxLjYsMTQxLjkgMTQxLjgsMTQxLjggWiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0ib2N0by1ib2R5Ij48L3BhdGg+PC9zdmc+PC9hPjxzdHlsZT4uZ2l0aHViLWNvcm5lcjpob3ZlciAub2N0by1hcm17YW5pbWF0aW9uOm9jdG9jYXQtd2F2ZSA1NjBtcyBlYXNlLWluLW91dH1Aa2V5ZnJhbWVzIG9jdG9jYXQtd2F2ZXswJSwxMDAle3RyYW5zZm9ybTpyb3RhdGUoMCl9MjAlLDYwJXt0cmFuc2Zvcm06cm90YXRlKC0yNWRlZyl9NDAlLDgwJXt0cmFuc2Zvcm06cm90YXRlKDEwZGVnKX19QG1lZGlhIChtYXgtd2lkdGg6NTAwcHgpey5naXRodWItY29ybmVyOmhvdmVyIC5vY3RvLWFybXthbmltYXRpb246bm9uZX0uZ2l0aHViLWNvcm5lciAub2N0by1hcm17YW5pbWF0aW9uOm9jdG9jYXQtd2F2ZSA1NjBtcyBlYXNlLWluLW91dH19PC9zdHlsZT4NCg0KPHNjcmlwdD4NCiQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uICgpIHsNCiAgICAkKCdwcmUucicpLmFkZENsYXNzKCdpbmRlbnQnKTsNCn0pOw0KPC9zY3JpcHQ+DQoNCiZuYnNwOw==